import LSU from "@/util/LocalStorageUtil.ts";
import IndexDatabase, {type AddData, type UpdateData} from "@/store/IndexDatabase.ts";
import LoggerManager from "@/log/LoggerManager.ts";

const log = LoggerManager.getLogger("IndexDBWrapper");
const DB_VERSION_KEY = "summer.mangosteen.db-version";
/**
 * indexDB使用封装类, 用户应该直接调用这个类对数据库进行操作
 * 禁止直接实例化原始类IndexDatabase
 */
export default class IndexDBWrapper {
    private static readonly instance: IndexDBWrapper = new IndexDBWrapper();
    private idb: IndexDatabase | null;
    private databaseVersion: number;
    private readonly dbName: string;
    private readonly tableName: string;
    private readonly primaryKey = "id";
    private readonly searchIndex = "username";

    // 私有化构造器
    private constructor() {
        this.databaseVersion = this.getDatabaseVersionFromLocal();
        this.dbName = import.meta.env.VITE_INDEX_DB_NAME;
        this.tableName = import.meta.env.VITE_INDEX_DB_USE_REQUEST_CACHE_NAME;
        this.idb = this.initDB();

    }

    /**
     * 初始化数据库处理类
     */
    private initDB() {
        return new IndexDatabase(this.dbName, this.databaseVersion, this.tableName, this.primaryKey, this.searchIndex);
    }

    /**
     * 唯一获取数据库包装类对象的方法
     */
    public static getInstance(): IndexDBWrapper {
        return IndexDBWrapper.instance;
    }

    /**
     * 添加新数据到数据库
     * @param data 需要添加的数据
     * @returns 添加成功返回添加的id, 添加失败返回0
     */
    public async add(data: AddData) {
        try {
            return await this.idb?.add(data);
        } catch (e: unknown) {
            log.error("Add data failure, ", e);
            return 0;
        }
    }

    /**
     * 更新数据库中的数据
     * @param data 需要更新的数据
     * @returns 更新成功返回数据id, 添加失败返回0
     */
    public async update(data: UpdateData) {
        try {
            return await this.idb?.add(data, true);
        } catch (e: unknown) {
            log.error("Update data failure, ", e);
            return 0;
        }
    }

    /**
     * 根据主键查找数据
     * @param primaryKey 数据主键的值
     */
    public async queryByPrimaryKey<T extends object>(primaryKey: string | number): Promise<T | null> {
        try {
            return await this.idb?.queryByPrimaryKey(primaryKey) as T;
        } catch (e: unknown) {
            log.error("Query data failure, ", e);
            return null;
        }
    }

    /**
     * 根据数据库索引查找数据
     * @param {string} indexField 索引字段
     * @param {string} searchValue 索引字段的值
     * @return 0 或者 1条数据
     */
    public async queryByIndexOne<T extends object>(indexField: string, searchValue: string): Promise<T | null> {
        try {
            return await this.idb?.queryByIndexOne(indexField, searchValue) as T;
        } catch (e: unknown) {
            log.error("Query data failure, ", e);
            return null;
        }
    }

    /**
     * 根据数据库索引查找数据
     * @param {string} indexField 索引字段
     * @param {string} searchValue 索引字段的值
     */
    public async queryByIndexList<T extends object>(indexField: string, searchValue: string): Promise<T[] | null> {
        try {
            if (this.idb){
                const res = this.idb.queryByIndexList(indexField, searchValue);
                return await (res as Promise<T[]>)
            }else {
                return null;
            }
        } catch (e: unknown) {
            log.error("Query data failure, ", e);
            return null;
        }
    }

    /**
     * 查找全部数据
     */
    public async queryAll<T extends object>(): Promise<T[] | null> {
        try {
            if (this.idb){
                const res = this.idb.queryAll();
                return await (res as Promise<T[]>)
            }else {
                return null;
            }
        } catch (e: unknown) {
            log.error("Query data failure, ", e);
            return null;
        }
    }

    /**
     * 根据主键删除数据
     * @param primaryKey 数据主键的值
     */
    public async deleteByPrimaryKey(primaryKey: number) {
        try {
            return await this.idb?.deleteByPrimaryKey(primaryKey);
        } catch (e: unknown) {
            log.error("Delete data by primary failure, ", e);
            return false;
        }
    }

    /**
     * 根据索引字段删除数据
     * @param indexField 索引字段
     * @param searchValue 索引字段的值
     * @param more 是否删除多个值
     */
    public async deleteByIndex(indexField: string, searchValue: string, more?: boolean) {
        try {
            return await this.idb?.deleteByIndex(indexField, searchValue, more);
        } catch (e: unknown) {
            log.error("Delete data by index failure, ", e);
            return false;
        }
    }

    public async showDatabaseInfo() {
        try {
            return await this.idb?.showDatabaseInfo();
        }catch (e: unknown){
            log.error("Show database info failure, ", e);
        }
    }

    /**
     * 创建字段索引
     * @param field 字段名字
     * @param unique 字段值是否唯一
     * @returns 创建成功返回字段索引名字, 创建失败返回null
     */
    public async createIndex(field: string, unique?: boolean): Promise<string | null> {
        const newVersion = this.getDatabaseVersionFromLocal() + 1;
        try {
            this.reinitialize();
            if (this.idb) {
                const res = await this.idb.createIndex(field, newVersion, unique);
                log.debug(`Field index [ ${field} ] create success.`, res);
                return res.name;
            }
            log.debug("Create field failure, database is null.")
            return null;
        } catch (e: unknown) {
            log.error("Create filedIndex failure, ", e);
            return null;
        } finally {
            this.updateDatabaseVersionToLocal(newVersion);
        }
    }

    /**
     * 删除字段索引
     * @param indexName 索引名字
     */
    public async deleteIndex(indexName: string) {
        const newVersion = this.getDatabaseVersionFromLocal() + 1;
        try {
            this.reinitialize();
            if (this.idb) {
                return await this.idb.deleteIndex(indexName, newVersion);
            }
            return false;
        } catch (e: unknown) {
            log.error("Delete filedIndex failure, ", e);
            return false;
        } finally {
            this.updateDatabaseVersionToLocal(newVersion);
        }
    }

    /**
     * 关闭数据库连接
     */
    public async closeDB() {
        try {
            await this.idb?.close();
            this.idb = null;
        } catch (e: unknown) {
            log.debug("Close database failure,", e);
        }
    }

    /*
    * 重新初始化数据库
     */
    public reinitialize() {
        if (this.idb) {
            return;
        }
        this.idb = this.initDB();
    }

    /**
     * 清空数据库中的存储器
     */
    public async clear() {
        try {
            await this.idb?.clear();
        } catch (e: unknown) {
            log.debug("Clear database store failure,", e);
        }
    }

    /**
     * 删除当前数据库
     */
    public async deleteDatabase() {
        await this.closeDB();
        try {
            await IndexDatabase.deleteDatabase(this.dbName);
            this.updateDatabaseVersionToLocal(1);
        } catch (e: unknown) {
            log.debug("Delete database failure,", e);
        }
    }

    /**
     * 从本地存储获取数据库版本号
     */
    private getDatabaseVersionFromLocal(): number {
        const version = LSU.getNumber(DB_VERSION_KEY);
        this.databaseVersion = version;
        return version;
    }

    /**
     * 更新本地存储中的数据库版本号
     */
    private updateDatabaseVersionToLocal(newVersion: number) {
        this.databaseVersion = newVersion;
        LSU.set(DB_VERSION_KEY, String(newVersion));
    }
}